<html>
<head><meta charset="utf-8"><title>Desugaring · t-compiler/rust-analyzer · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/index.html">t-compiler/rust-analyzer</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Desugaring.html">Desugaring</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="180913586"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Desugaring/near/180913586" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Desugaring.html#180913586">(Nov 16 2019 at 14:09)</a>:</h4>
<p>Stream for <a href="https://github.com/rust-analyzer/rust-analyzer/issues/2236" target="_blank" title="https://github.com/rust-analyzer/rust-analyzer/issues/2236">https://github.com/rust-analyzer/rust-analyzer/issues/2236</a></p>



<a name="180913645"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Desugaring/near/180913645" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Desugaring.html#180913645">(Nov 16 2019 at 14:10)</a>:</h4>
<p><span class="user-mention" data-user-id="248906">@cjgillot</span> yep, what you've written in the issue is correct!</p>



<a name="180913667"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Desugaring/near/180913667" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Desugaring.html#180913667">(Nov 16 2019 at 14:11)</a>:</h4>
<p>One thing to add though, is that there are two paths for <code>CST -&gt; AST</code> (or <code>ast -&gt; hir</code>, if using, rust-analyzer terminlogy (which is confusing :( ))</p>



<a name="180913710"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Desugaring/near/180913710" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Desugaring.html#180913710">(Nov 16 2019 at 14:12)</a>:</h4>
<p>The first path is when we do lowering: we start with function/static/const, and recursively lower every expression</p>



<a name="180913734"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Desugaring/near/180913734" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Desugaring.html#180913734">(Nov 16 2019 at 14:13)</a>:</h4>
<p>There's a second path thogh: <code>SourceAnalyzer::expr_id</code>. This is invoked by an IDE. IDE has a CST  for a specific expression, and it wants to get AST for this expression (as opposed to AST for the whole function)</p>



<a name="180913736"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Desugaring/near/180913736" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Desugaring.html#180913736">(Nov 16 2019 at 14:13)</a>:</h4>
<p>That's why, when lowring, we maintain both forward and backward maps</p>



<a name="180913788"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Desugaring/near/180913788" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Desugaring.html#180913788">(Nov 16 2019 at 14:14)</a>:</h4>
<p>And the problem is indeed that these maps miss some entries due to the way desugaring work, and in general <em>feel</em> imprecise. </p>
<p>I don't know, maybe the solution here is just to refactor these bits and put behind nicer interfaces (like removing Either's), but maybe it's something bigger</p>



<a name="180914023"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Desugaring/near/180914023" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> cjgillot <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Desugaring.html#180914023">(Nov 16 2019 at 14:21)</a>:</h4>
<p>Ok, I start to grasp a bit the issue. A first way forward would be to have all the lowering in one place. Then, we will have to ensure through typing that all the <code>hir</code> nodes have an <code>ast</code> counterpart. These two may lead to a significant step forward.</p>



<a name="180914132"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Desugaring/near/180914132" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Desugaring.html#180914132">(Nov 16 2019 at 14:24)</a>:</h4>
<p>Looks good to me!</p>
<p>I think we might also want to define some <em>type</em> which describes the lowring. Like, <code>ast &lt;-&gt; hir</code> map should be 1-to-many, so that we can say "this <em>if let</em> expression got lowered to this bunch of expressions".</p>



<a name="180914276"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Desugaring/near/180914276" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Desugaring.html#180914276">(Nov 16 2019 at 14:29)</a>:</h4>
<p>Or, and another complication is that there may be different types on the <code>ast</code> side (that's where the Eithers come from)</p>



<a name="181059164"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Desugaring/near/181059164" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> cjgillot <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Desugaring.html#181059164">(Nov 18 2019 at 21:38)</a>:</h4>
<p>Hi @matklad. I have an issue about the missing AST nodes. When there are missing constructors AST blocks, we have to invent a <code>Missing</code> HIR node. That node can not be mapped to an AST node. How should these be taken into account?</p>



<a name="181089389"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Desugaring/near/181089389" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Desugaring.html#181089389">(Nov 19 2019 at 07:54)</a>:</h4>
<p>Good question!</p>
<p>I think it makes sense that this node does not have a corresponding mapping back to the source. If you want to report an error for an expression, but the expr is  a synthesized <code>Missing</code>, you actually <em>shouldn't</em> be able to report an error.</p>



<a name="181089414"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Desugaring/near/181089414" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Desugaring.html#181089414">(Nov 19 2019 at 07:55)</a>:</h4>
<p>That seems like the signature should be like <code>-&gt; Result&lt;SyntaxNode, ExprMissingError&gt;</code>, and we might, or might not want to try to express this in the type system</p>



<a name="181089458"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Desugaring/near/181089458" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Desugaring.html#181089458">(Nov 19 2019 at 07:56)</a>:</h4>
<p>(this: the fact that only non-missing expressions have sources)</p>



<a name="181660684"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Desugaring/near/181660684" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> cjgillot <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Desugaring.html#181660684">(Nov 22 2019 at 17:43)</a>:</h4>
<p>I have an issue with the synthetic HIR nodes that come from desugaring. A possibility is to attach those to the containing expression. This would cause some hir::Expr nodes to back-reference to a ast::Pat node and conversely. Do we really need to preserve the typing in this direction?</p>



<a name="181661289"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Desugaring/near/181661289" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Desugaring.html#181661289">(Nov 22 2019 at 17:49)</a>:</h4>
<p><span class="user-mention" data-user-id="248906">@cjgillot</span> could you give an example?</p>



<a name="181663601"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Desugaring/near/181663601" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> cjgillot <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Desugaring.html#181663601">(Nov 22 2019 at 18:16)</a>:</h4>
<p>The desugaring of <code>WhileLet</code> creates 2 desugared expressions, a <code>break</code> and a <code>match</code>, as well as a pattern <code>_</code>.</p>



<a name="181663775"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Desugaring/near/181663775" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> cjgillot <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Desugaring.html#181663775">(Nov 22 2019 at 18:18)</a>:</h4>
<p>The only AST node to which back-map the pattern is the <code>WhileLet</code> node, but it is an expression node, not a pattern node.</p>



<a name="181664191"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Desugaring/near/181664191" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Desugaring.html#181664191">(Nov 22 2019 at 18:23)</a>:</h4>
<p>Aha! I guess, if we want to go fully strongly typed, we want to map it to</p>
<div class="codehilite"><pre><span></span><span class="k">enum</span> <span class="nc">PatternSugar</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">Pat</span><span class="p">(</span><span class="n">ast</span>::<span class="n">Pat</span><span class="p">),</span><span class="w"></span>
<span class="w">    </span><span class="n">WhileLetSugar</span><span class="p">(</span><span class="n">ExprId</span><span class="p">),</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</pre></div>



<a name="181664692"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Desugaring/near/181664692" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> cjgillot <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Desugaring.html#181664692">(Nov 22 2019 at 18:29)</a>:</h4>
<p>I was trying to get rid of the typing to make lowering easier, but this was should be better for error reporting.</p>



<a name="181761508"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Desugaring/near/181761508" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> cjgillot <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Desugaring.html#181761508">(Nov 24 2019 at 13:41)</a>:</h4>
<p>Hi. I have some doubt about the handling of missing expression nodes. At the moment, new <code>ExprId</code>s and <code>PatId</code>s are allocated each time, with no associated information. What about changing the <code>ExprId</code> in the HIR to <code>Option&lt;ExprId&gt;</code> and handle missing nodes using None value? This would allow to completely remove that special case from lowering and have complete HIR-&gt;AST mapping. Are there downstream constraints against that?</p>



<a name="181761665"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Desugaring/near/181761665" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Desugaring.html#181761665">(Nov 24 2019 at 13:46)</a>:</h4>
<p>Yep, this would unfortunatelly complicate furter analisys. Like, suppose we have something like <code>if [missing] { then } else { otherwise }</code>.</p>
<p>If the lowring produces <code>Expr::Missing</code> for <code>[missing]</code>, the typechecker assigns a fresh variable to this expr, it's inferred to <code>bool</code>, and everything typechecks, without any explicit handling. At the same time, the error is reported at the lowering phase. </p>
<p>If, OTOH, we use an <code>Option&lt;Expr&gt;</code> representation, than every bit of the typechecker has to care about this</p>



<a name="181761865"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Desugaring/near/181761865" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> cjgillot <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Desugaring.html#181761865">(Nov 24 2019 at 13:53)</a>:</h4>
<p>Ok. Do you have a pointer to a code block which would be strongly impacted? There may be some middle ground to reach.</p>



<a name="181761978"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Desugaring/near/181761978" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Desugaring.html#181761978">(Nov 24 2019 at 13:56)</a>:</h4>
<p><span class="user-mention" data-user-id="248906">@cjgillot</span> that would be <code>InferenceContext::infer_expr_inner</code></p>



<a name="181762036"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Desugaring/near/181762036" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Desugaring.html#181762036">(Nov 24 2019 at 13:58)</a>:</h4>
<p>In general, it seems like upper layers would prefer <code>Option&lt;ExprId&gt;</code> repr, while lower layers benefit from <code>Expr::Missing</code> repr. </p>
<p>Ideally, the desugaring infra should be the place which cleanly separates both worlds.</p>



<a name="181762131"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Desugaring/near/181762131" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> cjgillot <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Desugaring.html#181762131">(Nov 24 2019 at 14:01)</a>:</h4>
<p>In that case, <code>infer_expr</code> would be responsible for unwrapping the <code>Option&lt;ExprId&gt;</code>, and <code>infer_expr_inner</code> would barely change.</p>



<a name="181762294"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Desugaring/near/181762294" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Desugaring.html#181762294">(Nov 24 2019 at 14:05)</a>:</h4>
<p>There would be at least some subtelities. For example, optional expressions, like the else branch of <code>if</code>, would become an awkward <code>Option&lt;Option&lt;ExprId&gt;&gt;</code>.</p>



<a name="181762348"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Desugaring/near/181762348" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Desugaring.html#181762348">(Nov 24 2019 at 14:06)</a>:</h4>
<p>Though that can fixed by using a dedicated enum instead of inner options</p>



<a name="181762374"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Desugaring/near/181762374" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Desugaring.html#181762374">(Nov 24 2019 at 14:07)</a>:</h4>
<p>And I think that approach has some merit: in particular, it would be impossible to report errors for missing expressions...</p>



<a name="181762375"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Desugaring/near/181762375" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Desugaring.html#181762375">(Nov 24 2019 at 14:07)</a>:</h4>
<p><span aria-label="thinking" class="emoji emoji-1f914" role="img" title="thinking">:thinking:</span></p>



<a name="181762380"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/185405-t-compiler/rust-analyzer/topic/Desugaring/near/181762380" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> matklad <a href="https://rust-lang.github.io/zulip_archive/stream/185405-t-compiler/rust-analyzer/topic/Desugaring.html#181762380">(Nov 24 2019 at 14:07)</a>:</h4>
<p>lark used an interesting type for similar purposes: <code>Result&lt;T, ErrorReported&gt;</code></p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>